home *** CD-ROM | disk | FTP | other *** search
-
- #include <stdlib.h>
- #ifdef MYDIR
- #else
- #include "TwoDView.h"
- #include "TwoDTSP.h"
- #include <appkit/graphics.h>
- #endif
- #include <math.h>
- #include <limits.h>
- #include <stdio.h>
- #include "tspheaders.h"
- #include "prototypes.h"
- /************************************************************************/
- /* This function implements the Farthest Insertion Algorithm for the
- Travelling Salesperson Algorithm. It provides an approximate optimal
- value rather than the optimal value.
-
- Reference: Lawler, Lenstra, et. al., The Traveling Salesman [sic] Problem,
- 1985, Wiley and Sons, p 226.
-
- */
- /************************************************************************/
- /* Parameters: TwoDView *self: Ye Old Drawing Object
-
- float *Data: Pointer to the list of points.
- Used to draw intermediate graph.
-
- float *Distance: Pointer to area that contains the
- Distances Between Each Pair of Cities
-
- int *Tour: Pointer to area that will contain the
- indices of the n arcs that are selected
- to be a part of the tour
-
- int NumberOfCities: Number of cities in the problem
- */
- /************************************************************************/
- /************************************************************************/
- #ifdef MYDIR
- float FarthestInsertion(float *Distance,int *Tour,int NumberOfCities) {
- #else
- float FarthestInsertion(TwoDView *self,float *data,float *Distance,int *Tour,
- int NumberOfCities) {
- #endif
- int i,j,k,m,x,y,I,J,
- From,To,CurrentCity,SubTourEnd,TourIndex,NewCity,
- City1,City2,LeavingArc;
- int *OnTour, *TourCities;
- float NewDistance,MinDistance,ThisDistance,OptimalValue;
- char msg[256];
-
- /* allocate space for OnTour and TourCities */
- OnTour = (int *)malloc(NumberOfCities*sizeof(int));
- TourCities = (int *)malloc(NumberOfCities*sizeof(int));
- if (OnTour == (int *) 0)
- printf("Malloc for OnTour failed. \n");
- if (TourCities == (int *) 0)
- printf("Malloc for TourCities failed. \n");
- for (i=0;i<NumberOfCities;i++) {
- OnTour[i] = 0;
- }
- for (i=0;i<NumberOfCities;i++) {
- TourCities[i] = 0;
- }
-
- #ifdef DEBUGMYDIR
- for (i=0;i<(NumberOfCities-1)*NumberOfCities/2;i++) {
- printf("Distance[%d] = %f; \n",i,Distance[i]);
- }
- #endif
-
- /* find the two cities with the maximum distance */
- /* these two cities make up the initial subtour */
- NewDistance = FarthestCities(Distance,&From,&To,NumberOfCities);
-
- /* if NewDistance doesn't change, there is a problem ... */
- if (NewDistance == 0) {
- printf("Error no initial subtour found. \n");
- }
- #ifdef DEBUGMYDIR
- else {
- printf("initial subtour \n");
- printf("from %d to %d distance %f \n",From,To,NewDistance);
- }
- #endif
-
- /* given a subtour of m cities, add city k with minimum insertion cost */
- /* cost of inserting city k between cities i and j =
- Distance(i,k) + Distance(k,j) - Distance(i,j) */
-
- /* OnTour is a list of cities on the tour already. */
- Tour[0] = Tour[3] = From;
- Tour[1] = Tour[2] = To;
- OnTour[From] = OnTour[To] = 1;
- TourCities[0] = From;
- TourCities[1] = To;
- OptimalValue = 2*NewDistance;
-
- SubTourEnd = 1;
- TourIndex = -1;
- NewCity = NumberOfCities;
- NewDistance = 0;
-
- /* keep adding cities until you include all NumberOfCities of them */
- while (SubTourEnd < NumberOfCities-1) {
- #ifdef DEBUGMYDIR
- printf("Start of Iteration with %d cities in tour \n",SubTourEnd+1);
- #endif
- /* at the end of this while loop, there will be a new city to insert */
- while (TourIndex < SubTourEnd) {
- /* look at the next city already on the tour */
- TourIndex+=1;
- CurrentCity = TourCities[TourIndex];
- #ifdef DEBUGMYDIR
- printf("Looking at city %d \n",CurrentCity);
- #endif
- /* look at all arcs starting at CurrentCity */
- I = ArcIndex(CurrentCity,NumberOfCities);
- J = ArcIndex((CurrentCity+1),NumberOfCities);
- for (i=I;i<J;i++) {
- /* j = terminating end of this arc */
- j = i-I+CurrentCity+1;
- /* if the city at the other end isn't already on the tour ...*/
- if (!OnTour[j]) {
- /* Is the arc a new candidate for insertion? */
- k = kfrom(CurrentCity,j,NumberOfCities);
- if (Distance[k] > NewDistance) {
- #ifdef DEBUGMYDIR
- printf("Changing cities from %d to %d \n",NewCity,j);
- printf("Looking at city %d \n",CurrentCity);
- #endif
- NewDistance = Distance[k];
- NewCity = j;
- }
- }
- }
-
- /* look at all arcs ending at CurrentCity */
- for (m=0;m<CurrentCity;m++) {
- /* if the starting city isn't already on the tour ...*/
- if (!OnTour[m]) {
- /* Is this arc a new candidate for insertion? */
- k = kfrom(m,CurrentCity,NumberOfCities);
- if (Distance[k] > NewDistance) {
- #ifdef DEBUGMYDIR
- printf("Changing cities from %d to %d \n",NewCity,m);
- #endif
- NewDistance = Distance[k];
- NewCity = m;
- }
- }
- }
- }
-
- if (NewCity >= NumberOfCities) {
- printf("Error: new city has not been found for tour. \n");
- CurrentCity = SubTourEnd = NumberOfCities;
- OptimalValue = -1;
- }
- else {
- /* find two cities on the tour, City1 and City2 such that the
- distance from City1 to the NewCity plus the distance from
- the NewCity to City2 - the distance from City1 to City2 is
- minimized. */
- k = 0;
- MinDistance = INT_MAX;
- #ifdef DEBUGMYDIR
- printf("NewCity is %d SubTourEnd %d \n",NewCity,SubTourEnd);
- #endif
- while (k <= 2*SubTourEnd) {
- City1 = Tour[k];
- City2 = Tour[k+1];
- ThisDistance = Distance[kfrom(City1,NewCity,NumberOfCities)] +
- Distance[kfrom(City2,NewCity,NumberOfCities)] -
- Distance[kfrom(City1,City2,NumberOfCities)];
- #ifdef DEBUGMYDIR
- printf("This %f Min %f City1 %d City2 %d \n",ThisDistance, MinDistance,City1,City2);
- #endif
- if (ThisDistance < 0) {
- printf("Error: ThisDistance = %f for City1 %f City2 %f NewCity %f \n",
- City1,City2,NewCity);
- }
-
- if (ThisDistance < MinDistance) {
- MinDistance = ThisDistance;
- LeavingArc = k;
- }
- k+=2;
- }
-
- if (MinDistance == INT_MAX) {
- printf("Error: wasn't able to find a spot for %d \n",NewCity);
- }
-
- /* arc in Tour starting at LeavingArc is replaced by arcs
- between Tour[LeavingArc] and NewCity and arc between
- NewCity and Tour[LeavingArc+1]. */
-
- /* add the new arc going from NewCity to Tour[LeavingArc+1] */
- #ifdef DEBUGMYDIR
- printf("adding arc from %d to %d \n",NewCity,Tour[LeavingArc+1]);
- #else
- sprintf(msg,"add arc %d to %d \n",NewCity,Tour[LeavingArc+1]);
- STATUS(msg);
- #endif
- SubTourEnd+=1;
- Tour[2*SubTourEnd] = NewCity;
- Tour[2*SubTourEnd+1] = Tour[LeavingArc+1];
- OnTour[NewCity] = 1;
- TourCities[SubTourEnd] = NewCity;
-
- #ifdef DEBUGMYDIR
- printf("replacing arc from %d to %d with %d to %d \n",
- Tour[LeavingArc],Tour[LeavingArc+1],Tour[LeavingArc],NewCity);
- #else
- sprintf(msg,"replacing arc from %d to %d with %d to %d \n",
- Tour[LeavingArc],Tour[LeavingArc+1],Tour[LeavingArc],NewCity);
- STATUS(msg);
- #endif
- Tour[LeavingArc+1] = NewCity;
-
- /* update the Optimal Value */
- OptimalValue+=MinDistance;
-
- #ifdef DEBUGMYDIR
- printf("addding %f to Opval to get %f \n",MinDistance,OptimalValue);
- #else
- sprintf(msg,"addding %f to Opval to get %f \n",MinDistance,OptimalValue);
- STATUS(msg);
- #endif
- }
-
- /* get ready to start at the top of the list again */
- TourIndex = -1;
- NewDistance = 0;
- NewCity = NumberOfCities;
-
- #ifdef DEBUGMYDIR
- /* print out current subtour */
- for (i=0;i<2*(SubTourEnd+1);i++) {
- printf("i tour %d %d \n",i,Tour[i]);
- }
- #endif
- #ifdef MYDIR
- #else
- /* draw the intermediate tour */
- PSnewinstance();
- for(i=0;i<2*(SubTourEnd+1);i+=2) {
- x = Tour[i];
- y = Tour[i+1];
- [self drawEdge:X(x):Y(x):X(y):Y(y)];
-
- }
- NXPing();
- [self->optimalValueField setFloatValue: OptimalValue at: 0];
- usleep(self->drawTime);
- #endif
-
- }
-
- /* clean up */
- free(OnTour);
-
- /* return the optimal value */
- return(OptimalValue);
- }
-
-